#include <iostream>
#include <windows.h>
using namespace std;

const int num = 3200;
int arr[num];
int matrix[num][num];
int sum[num];

int COUNT = 150;//ͨ���޸�COUNT����ʹ�ú��Ĵ�������ж���ظ�ƽ����ʱ

void init() {
    for (int i = 0; i < num; i++) {
        arr[i] = i;
        sum[i] = 0;
    }
    for (int i = 0; i < num; i++) {
        for (int j = 0; j < num; j++) {
            matrix[i][j] = i + j;
        }
    }
}

void matrix_normal() {
    long long int head, tail, freq;
    for (int i = 0; i < num; i++) {
        sum[i] = 0;
    }
    QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
    QueryPerformanceCounter((LARGE_INTEGER*)&head);
    for (int c = 0; c < COUNT; c++) {
        for (int i = 0; i < num; i++) {
            for (int j = 0; j < num; j++) {
                sum[i] += arr[j] * matrix[j][i];
            }
        }
    }
    QueryPerformanceCounter((LARGE_INTEGER*)&tail);
    cout << "matrix_normal_col:" << (tail - head) * 1000.0 / freq / COUNT << "ms" << endl;
}

void matrix_cache() {
    long long int head, tail, freq;
    for (int i = 0; i < num; i++) {
        sum[i] = 0;
    }
    QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
    QueryPerformanceCounter((LARGE_INTEGER*)&head);
    for (int c = 0; c < COUNT; c++) {
        for (int i = 0; i < num; i++) {
            for (int j = 0; j < num; j++) {
                sum[j] += arr[i] * matrix[i][j];
            }
        }
    }
    QueryPerformanceCounter((LARGE_INTEGER*)&tail);
    cout << "matrix_cache_row:" << (tail - head) * 1000.0 / freq / COUNT << "ms" << endl;
}

void matrix_unroll() {
    for (int i = 0; i < num; i++) {
        sum[i] = 0;
    }
    long long int head, tail, freq;
    QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
    QueryPerformanceCounter((LARGE_INTEGER*)&head);
    for (int c = 0; c < COUNT; c++) {
        for (int j = 0; j < num; j += 10){
            int tmp0 = 0, tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0, tmp5 = 0, tmp6 = 0, tmp7 = 0, tmp8 = 0, tmp9 = 0;
            for (int i = 0; i < num; i++){
                tmp0 += arr[j + 0] * matrix[j + 0][i];
                tmp1 += arr[j + 1] * matrix[j + 1][i];
                tmp2 += arr[j + 2] * matrix[j + 2][i];
                tmp3 += arr[j + 3] * matrix[j + 3][i];
                tmp4 += arr[j + 4] * matrix[j + 4][i];
                tmp5 += arr[j + 5] * matrix[j + 5][i];
                tmp6 += arr[j + 6] * matrix[j + 6][i];
                tmp6 += arr[j + 6] * matrix[j + 6][i];
                tmp7 += arr[j + 7] * matrix[j + 7][i];
                tmp8 += arr[j + 8] * matrix[j + 8][i];
                tmp9 += arr[j + 9] * matrix[j + 9][i];
            }
            sum[j + 0] = tmp0;
            sum[j + 1] = tmp1;
            sum[j + 2] = tmp2;
            sum[j + 3] = tmp3;
            sum[j + 4] = tmp4;
            sum[j + 5] = tmp5;
            sum[j + 6] = tmp6;
            sum[j + 7] = tmp7;
            sum[j + 8] = tmp8;
            sum[j + 9] = tmp9;
        }
    }
    QueryPerformanceCounter((LARGE_INTEGER*)&tail);
    cout << "matrix_unroll:" << (tail - head) * 1000.0 / freq / COUNT << "ms" << endl;
}

int main()
{
    init();
    matrix_normal();
    matrix_cache();
    matrix_unroll();

    return 0;
}